﻿namespace Stopwatch.Storage
{
    using System;
    using System.IO;
    using System.IO.IsolatedStorage;
    using System.Text;
    using Newtonsoft.Json;

    internal class IsolatedStorage : IStorage
    {
        IsolatedStorageFile storage { get { return IsolatedStorageFile.GetUserStoreForApplication(); } }

        public void Write<T>(T obj, string key = null) where T : class
        {
            if (string.IsNullOrEmpty(key))
            {
                key = ParsePath(obj.GetType());
            }

            try
            {
                using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(key, FileMode.Create, storage))
                using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                {
                    JsonSerializer serializer = new JsonSerializer();
                    serializer.Serialize(new JsonTextWriter(sw), obj);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }

        public T Read<T>(string key = null) where T : class
        {
            if (string.IsNullOrEmpty(key))
            {
                key = ParsePath(typeof(T));
            }

            if (!Exists(key))
            {
                return null;
            }

            try
            {
                using (IsolatedStorageFileStream fs = new IsolatedStorageFileStream(key, FileMode.OpenOrCreate, storage))
                using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                {
                    JsonSerializer serializer = new JsonSerializer();
                    return serializer.Deserialize<T>(new JsonTextReader(sr));
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }

        public void Delete<T>() where T : class
        {
            Delete(ParsePath(typeof(T)));
        }

        public void Delete(string key)
        {
            if (Exists(key))
            {
                try
                {
                    storage.DeleteFile(key);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    throw;
                }
            }
        }

        public bool Exists<T>() where T : class
        {
            return Exists(ParsePath(typeof(T)));
        }

        public bool Exists(string key)
        {
            try
            {
                return storage.FileExists(key);
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }

        static string ParsePath(Type type)
        {
            return string.Format("{0}.json", type.FullName).ToLower();
        }
    }
}
